
#If Not (PocketPC Or Smartphone) Then

Imports System.IO
Imports System.Threading
Imports std

Public Class configMonitor
    Inherits configParser

    'should not change this too large, as if file could not access forever, monitor would be out of function
    Public reopenTimes As Int64 = 64
    Public enableRaisingEvents As Boolean = True
    Public closeWhenConfigDeleted As Boolean = False
    Public Event configChanged()
    Public Event configfileDeleted()
    'assumption to saferFileSystemWatcher, it should always raiseEvent one by one.
    Private WithEvents monitor As saferFileSystemWatcher = Nothing
    Private _configRefreshing As Boolean = False

    Public Function configRefreshing() As Boolean
        Return _configRefreshing
    End Function

    Public Function refreshing() As Boolean
        Return configRefreshing()
    End Function

    <Security.Permissions.PermissionSet(Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
    Public Overrides Function open(ByVal filename As String) As Boolean
        If MyBase.open(filename) Then
            If Not monitor Is Nothing Then
                monitor.Dispose()
                monitor = Nothing
            End If
            monitor = New saferFileSystemWatcher()
            monitor.NotifyFilter = NotifyFilters.LastWrite Or NotifyFilters.FileName
            Try
                monitor.Path = strleft(configfile(), strlen(configfile()) - strlen(Global.filename(configfile())))
                monitor.Filter = Path.GetFileName(configfile)
                monitor.EnableRaisingEvents = True
            Catch
                monitor_failmonitor()
            End Try

            Return True
        Else
            Return False
        End If
    End Function

    Public Overrides Sub close()
        If Not monitor Is Nothing Then
            monitor.EnableRaisingEvents = False
            monitor.Dispose()
            monitor = Nothing
        End If
        GC.KeepAlive(monitor)
        MyBase.close()
    End Sub

    Private Sub monitor_Changed(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) _
                                                                                                Handles monitor.Changed
        Dim i As Int64
        Dim rtn As Boolean = True
        For i = 0 To reopenTimes - 1
            rtn = open(configfile)
            If rtn Then
                Exit For
            Else
                sleep() 'wait for the file to be written
            End If
        Next
        assert(rtn, "failed to re-open configfile " + configfile())
        'if cannot reopen configfile after several tries, can only assert and exit application.
        'configParser can keep original config available before can read file again, so it's safe here.
        If enableRaisingEvents Then
            _configRefreshing = True
            RaiseEvent configChanged()
            _configRefreshing = False
        End If
    End Sub

    Private Sub monitor_Deleted(ByVal sender As Object, ByVal e As System.IO.FileSystemEventArgs) _
                                                                                                Handles monitor.Deleted
        If closeWhenConfigDeleted Then
            close()
        End If
        If enableRaisingEvents Then
            _configRefreshing = True
            RaiseEvent configfileDeleted()
            _configRefreshing = False
        End If
    End Sub

    Private Sub monitor_failmonitor() Handles monitor.failmonitor
        raiseError("cannot monitor config file, raise a deleted event if enabled.", errorHandle.errorType.exclamation)
        If enableRaisingEvents Then
            _configRefreshing = True
            RaiseEvent configfileDeleted()
            _configRefreshing = False
        End If
    End Sub

    Protected Overrides Sub Finalize()
        close()
        MyBase.Finalize()
    End Sub

    Public Shared Function defaultConfigDeletedOperation(ByVal restoreMS As Int64 _
                                                        , ByVal raiseTimes As Int32 _
                                                        , Optional ByVal configfile As String = Nothing) As Boolean
        Static deletedEventTimes As Int32 = 0
        Static lasttime As Date = New Date(0)
        If ticksToMilliseconds(Now.Ticks - lasttime.Ticks) > restoreMS Then
            deletedEventTimes = 0
        End If
        lasttime = New Date(Now.Ticks)
        deletedEventTimes += 1
        If deletedEventTimes = raiseTimes Then
            If Not isemptystring(configfile) Then
                raiseError("configfile " + configfile + " has been deleted, start failure action." _
                            , errorHandle.errorType.exclamation)
            Else
                raiseError("configfile has been deleted, start failure action." _
                            , errorHandle.errorType.exclamation)
            End If
            Return True
        Else
            Return False
        End If
    End Function
End Class

#End If
